package conversion.utils.converter;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
import com.google.gson.*;
import com.opencsv.CSVWriter;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.opencsv.CSVWriter;

import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;


/**
 * JsonProcessor 类用于处理JSON字符串，提供转换、格式化和缩进等操作。
 * @author ZJW
 * 版本：1.0
 */
public class JsonProcessor {


    /**
     * 验证json字符串的格式是否正确
     *
     * @param json 要验证的json字符串
     * @return 如果正确，则返回ture，否则反之，返回false
     */
    public static boolean isFormatValid(String json) {
        try {
            JsonParser parser = new JsonParser();
            parser.parse(json);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 将指定的json字符串美化排版
     * @param jsonString 要排版的json字符串
     * @return 美化好的json字符串
     */
    public static String formatJson(String jsonString) {
        Gson gson = new GsonBuilder().setPrettyPrinting().create();
        Object jsonObject = gson.fromJson(jsonString, Object.class);
        return gson.toJson(jsonObject);
    }


    /**
     * 移除 JSON 字符串的格式化。
     *
     * @param jsonString 包含格式化的 JSON 字符串
     * @return 不带格式化的 JSON 字符串
     */
    public static String removeFormatting(String jsonString) {
        // 解析 JSON 字符串为 JsonElement 对象
        JsonElement jsonElement = JsonParser.parseString(jsonString);

        // 创建 Gson 对象
        Gson gson = new Gson();

        // 将 JsonElement 对象转换为不带格式的 JSON 字符串
        return gson.toJson(jsonElement);
    }

    /**
     * 将JSON字符串格式转换成CSV字符串格式
     *
     * @param jsonString 要转换的JSON字符串
     * @return 转换后的CSV字符串
     */
    public static String convertToCSV(String jsonString) throws IOException {
        String csvString = "";
        // 创建一个ObjectMapper对象，用于将JSON字符串转换为Java对象
        ObjectMapper objectMapper = new ObjectMapper();


        // 使用ObjectMapper对象将JSON字符串转换为List<Map<String, String>>对象，其中Map的key是String类型，value是String类型
        List<Map<String, String>> dataList = objectMapper.readValue(jsonString, new TypeReference<List<Map<String, String>>>() {});
        // 创建一个StringWriter对象，用于将Java对象写入字符串
        StringWriter stringWriter = new StringWriter();
        // 创建一个CSVWriter对象，用于将Java对象写入CSV格式
        CSVWriter csvWriter = new CSVWriter(stringWriter);
        // 创建一个ArrayList对象，用于存储CSV文件的表头
        List<String> headers = new ArrayList<>();
        // 如果List对象不为空
        if (!dataList.isEmpty()) {
            // 将第一个Map对象的key集合添加到headers中
            headers.addAll(dataList.get(0).keySet());
            // 将headers转换为数组并写入CSVWriter对象中
            csvWriter.writeNext(headers.toArray(new String[0]));
            // 遍历List中的Map对象
            for (Map<String, String> dataMap : dataList) {
                // 创建一个ArrayList对象，用于存储当前行的数据
                List<String> rowData = new ArrayList<>();
                // 遍历headers中的表头
                for (String header : headers) {
                    // 将当前行对应表头的数据添加到rowData中
                    rowData.add(dataMap.get(header));
                }
                // 将rowData转换为数组并写入CSVWriter对象中
                csvWriter.writeNext(rowData.toArray(new String[0]));
            }
        }
        // 刷新CSVWriter对象
        csvWriter.flush();
        // 将StringWriter对象转换为字符串
        csvString = stringWriter.toString();
        // 关闭CSVWriter对象和StringWriter对象
        csvWriter.close();
        stringWriter.close();

        return csvString;
    }


    /**
     * 将JSON字符串转换为CSV格式。
     *
     * @param jsonString 输入的JSON字符串。
     * @return JSON数据的CSV表示。
     * @throws IOException 如果读取或写入数据时发生错误。
     */
    public static String enhancedConvertToCSV(String jsonString) throws IOException {
        String csvString = "";

        // 创建一个ObjectMapper对象，用于将JSON字符串转换为Java对象
        ObjectMapper objectMapper = new ObjectMapper();

        // 使用ObjectMapper对象将JSON字符串转换为JsonNode对象
        JsonNode jsonNode = objectMapper.readTree(jsonString);

        // 创建一个StringWriter对象，用于将Java对象写入字符串
        StringWriter stringWriter = new StringWriter();

        // 创建一个CSVWriter对象，用于将Java对象写入CSV格式
        CSVWriter csvWriter = new CSVWriter(stringWriter);

        // 递归处理JSON对象并将数据写入CSVWriter中
        processJsonNode("", jsonNode, csvWriter);

        // 刷新CSVWriter对象
        csvWriter.flush();

        // 将StringWriter对象转换为字符串
        csvString = stringWriter.toString();

        // 关闭CSVWriter对象和StringWriter对象
        csvWriter.close();
        stringWriter.close();

        return csvString;
    }

    /**
     * 递归处理JsonNode对象，并将数据写入CSVWriter。
     *
     * @param prefix    字段名的前缀。
     * @param node      当前要处理的JsonNode。
     * @param csvWriter 用于写入数据的CSVWriter对象。
     */
    private static void processJsonNode(String prefix, JsonNode node, CSVWriter csvWriter) {
        if (node.isObject()) {
            Iterator<Map.Entry<String, JsonNode>> fields = node.fields();
            while (fields.hasNext()) {
                Map.Entry<String, JsonNode> field = fields.next();
                String fieldName = field.getKey();
                JsonNode fieldValue = field.getValue();
                if (fieldValue.isArray()) {
                    processJsonArray(prefix + fieldName, fieldValue, csvWriter);
                } else if (fieldValue.isObject()) {
                    processJsonNode(prefix + fieldName + ".", fieldValue, csvWriter);
                } else {
                    String value = fieldValue.isNull() ? "" : fieldValue.asText();
                    csvWriter.writeNext(new String[]{prefix + fieldName, value});
                }
            }
        }
    }

    /**
     * 处理JsonNode数组，并将数据写入CSVWriter。
     *
     * @param prefix    字段名的前缀。
     * @param node      当前要处理的JsonNode。
     * @param csvWriter 用于写入数据的CSVWriter对象。
     */
    private static void processJsonArray(String prefix, JsonNode node, CSVWriter csvWriter) {
        if (node.isArray()) {
            for (int i = 0; i < node.size(); i++) {
                JsonNode element = node.get(i);
                if (element.isObject()) {
                    processJsonNode(prefix + "[" + i + "]", element, csvWriter);
                } else {
                    String value = element.isNull() ? "" : element.asText();
                    csvWriter.writeNext(new String[]{prefix, value});
                }
            }
        }
    }


    /**
     * 将json字符串转换成xml字符串
     *
     * @param json 要要转换的json字符串
     * @return 转换好的xml字符串
     */
    public static String convertToXML(String json){
        Document document = DocumentHelper.createDocument();
        Element root =  document.addElement("root"); //默认根节点
        JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject();
        Element el = toXML(jsonObject, root, null);
        return el.asXML();

    }

    /**
     * 将json字符串转换成xml
     *
     * @param jsonElement
     *            待解析json对象元素
     * @param parentElement
     *            上一层xml的dom对象
     * @param name
     *            父节点
     */
    private static Element toXML(JsonElement jsonElement, Element parentElement, String name) {
        if (jsonElement instanceof JsonArray) {
            //是json数据，需继续解析
            JsonArray sonJsonArray = (JsonArray)jsonElement;
            for (int i = 0; i < sonJsonArray.size(); i++) {
                JsonElement arrayElement = sonJsonArray.get(i);
                toXML(arrayElement, parentElement, name);
            }
        }else if (jsonElement instanceof JsonObject) {
            //说明是一个json对象字符串，需要继续解析
            JsonObject sonJsonObject = (JsonObject) jsonElement;
            Element currentElement = null;
            if (name != null) {
                currentElement = parentElement.addElement(name);
            }
            Set<Map.Entry<String, JsonElement>> set = sonJsonObject.entrySet();
            for (Map.Entry<String, JsonElement> s : set) {
                toXML(s.getValue(), currentElement != null ? currentElement : parentElement, s.getKey());
            }
        } else {
            //说明是一个键值对的key,可以作为节点插入了
//            addAttribute(parentElement, name, jsonElement.getAsString());
            //增加子节点，并为子节点赋值
            Element el = parentElement.addElement(name);
            el.addText(jsonElement.getAsString());

        }
        return parentElement;
    }


    /**
     * 将指定的json字符串转换成yaml字符串
     * @param jsonString 要转换的json字符串
     * @return 转换好的yaml字符串
     */
    public static String convertToYAML(String jsonString) throws JsonProcessingException {
        String yamlString = null;

        ObjectMapper mapper = new ObjectMapper(new YAMLFactory()
                .disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER)
                .enable(YAMLGenerator.Feature.INDENT_ARRAYS));

        // 从JSON字符串中读取数据并转换成Object对象
        Object obj = mapper.readValue(jsonString, Object.class);

        // 将转换后的Object写入到YAML格式字符串中
        yamlString = mapper.writeValueAsString(obj);

        return yamlString;
    }

}
